/**
 * Created by liu on 2019/10/23.
 * 主要分几个部分
 * 第一部分 基础通用功能
 * 第二部分 总结历来项目中用到的时间处理
 * 第三部分 string array等对象的 原型方法扩展 也很常用
 *
 * 锚点
 * accAdd 精确计算
 * gotoPart2 第二部分
 */

+(function (window) {
    'use strict'

    const regExp = {
        url: /^http[s]?:\/\/.*/, //URL地址
        isPhone: /^1[0-9]{10}$/,
        //判断是否为固话
        isTel: /^(400|800)([0-9\\-]{7,10})|(([0-9]{4}|[0-9]{3})([- ])?)?([0-9]{7,8})(([- 转])*([0-9]{1,4}))?$/,
        isEmail: /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/,
        isNumber: /^[0-9]*$/,//判断是否为数字
        discount: /(^0\.\d+$)|(^[01]$)/, //记一下 可鞥会常用 折扣 0-1的
        external: /^(https?:|mailto:|tel:|\/\/)/,// 判读是否为外链
        isUpperCase: /^[A-Z]+$/,//判断是否是大写字母
        isLowerCase: /^[a-z]+$/,//判断是否是小写字母
        isAlphabets: /^[A-Za-z]+$/,//判断是否是大写字母开头
        isChina: /^[\u4E00-\u9FA5]{2,4}$/,//判断是否中文
        //判断是否为IP
        isIP: /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/,
        isName: /^[\u4e00-\u9fa5a-zA-Z0-9]+$/,//判断是否是名称
        //判断是否是端口号
        isPort: /^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$/,
        //判断是否是身份证号(第二代)
        isIdCard: /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/,
        //判断是否为数字且最多两位小数
        isNum: /^\d+(\.\d{1,2})?$/,
        posInt: /^[0-9]+$/,
        isFloat: /^\d+(\.\d{1,4})?$/,
        //复杂日期判断  2023-11-30 00:00:00 -> true   2023-11-31 00:00:00 -> false
        isComplexDate: /^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29) (?:[01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/,
    }
    /**
     * 基础部分
     */
    var part1 = {
        ranStr: 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678',
        randomNum: '', //获取的随机数
        /**
         * 为空判断 注意 0
         * @param {*} cont
         * @returns
         */
        empty: function (cont) {
            if (cont === 0) return false
            return (cont == 'null' || cont == null || typeof (cont) == 'undefined' || cont == 'undefined' || cont == '') ? true : false
        },
        // 下边的这个方法是上边empty的复刻版，等于0的情况也返回true，认定为空
        zeroEmpty: function (cont) {
            return (cont == 'null' || cont == null || typeof (cont) == 'undefined' || cont == 'undefined' || cont == '' || cont == 0) ? true : false
        },

        getCharCount: function(str,char){
            var regex = new RegExp(char, 'g'); // 使用g表示整个字符串都要匹配
            var result = str.match(regex); //match方法可在字符串内检索指定的值，或找到一个或多个正则表达式的匹配。
            var count=!result ? 0 : result.length;
            return count;
        },
        /**
         * 判断Json类型是不是空 {}
         * @param cont
         */
        jsonEmpty:function (cont){
            return JSON.stringify(cont)=="{}"
        },
        /**
         * 统一正则验证
         * @param {*} reg
         * @param {*} str
         */
        regTest: function (reg, str) {
            if (!regExp.hasOwnProperty(reg)) return false;
            return regExp[reg].test(str);
        },
        //精确 加法
        accAdd: function (arg1, arg2) {
            var r1, r2, m, c
            try {
                r1 = arg1.toString().split('.')[1].length
            } catch (e) {
                r1 = 0
            }
            try {
                r2 = arg2.toString().split('.')[1].length
            } catch (e) {
                r2 = 0
            }
            c = Math.abs(r1 - r2)
            m = Math.pow(10, Math.max(r1, r2))
            if (c > 0) {
                var cm = Math.pow(10, c)
                if (r1 > r2) {
                    arg1 = Number(arg1.toString().replace('.', ''))
                    arg2 = Number(arg2.toString().replace('.', '')) * cm
                } else {
                    arg1 = Number(arg1.toString().replace('.', '')) * cm
                    arg2 = Number(arg2.toString().replace('.', ''))
                }
            } else {
                arg1 = Number(arg1.toString().replace('.', ''))
                arg2 = Number(arg2.toString().replace('.', ''))
            }
            return (arg1 + arg2) / m
        },

        //精确 减法
        accSub: function (arg1, arg2) {
            var r1 = 0,
                r2 = 0,
                r3 = 0
            try {
                r1 = (arg1 + '').split('.')[1].length
            } catch (err) {
                r1 = 0
            }
            try {
                r2 = (arg2 + '').split('.')[1].length
            } catch (err) {
                r2 = 0
            }
            r3 = Math.pow(10, Math.max(r1, r2))
            return (part1.accMul(arg1, r3) - part1.accMul(arg2, r3)) / r3
        },

        //精确 乘法
        accMul: function (arg1, arg2) {
            var m = 0,
                s1 = arg1.toString(),
                s2 = arg2.toString()
            try {
                m += s1.split('.')[1].length
            } catch (e) { }
            try {
                m += s2.split('.')[1].length
            } catch (e) { }
            return Number(s1.replace('.', '')) * Number(s2.replace('.', '')) / Math.pow(10, m)
        },

        //精确 除法
        accDiv: function (arg1, arg2) {
            var r1 = arg1 + '',
                r2 = arg2 + '',
                r3 = 0,
                r4 = 0
            try {
                r3 = r1.split('.')[1].length
            } catch (err) {
                r3 = 0
            }
            try {
                r4 = r2.split('.')[1].length
            } catch (err) {
                r4 = 0
            }
            return part1.accMul((Number(r1.replace('.', '')) / Number(r2.replace('.', ''))), Math.pow(10, r4 - r3))
        },
        // 数字 --> 单价，默认2位小数
        toPrice: function (price, n = 2) {
            return this.setTwoNum(price, n)
        },

        // 数字 --> 金额，默认2位小数，千分位显示
        toAmount: function (amount, n = 2) {
            return this.toThousands(this.setTwoNum(amount, n))
        },
        //小数转百分比 并默认保留2位小数
        toPercent: function (price, n) {
            var str = this.setTwoNum(Number(price * 100), n)
            str += '%'
            return str
        },
        //百分比转小数
        toPoint: function (price, n) {
            price = (price || '').toString()
            return this.setTwoNum(Number(price.replace('%', '') / 100), n)
        },
        isArray: function (obj) {
            return Object.prototype.toString.call(obj) == '[object Array]'
        },
        isObject: function (obj) {
            return Object.prototype.toString.call(obj) == '[object Object]'
        },
        isFunction: function (obj) {
            return typeof obj === 'function'
        },
        isBoolean: function (obj) {
            return typeof obj === 'boolean'
        },
        /*
        * uuid
        * 可以指定长度和基数
        * uuid(8, 2) // "01001010"  (base=2)
        * uuid(8, 10) // "47473046" (base=10)
        * uuid(8, 16) // "098F4D35" (base=16)
        * */
        uuid: function (len, radix) {
            var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
            var uuid = [],
                i;
            radix = radix || chars.length;
            if (len) {
                for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix]
            } else {
                var r
                uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'
                uuid[14] = '4'
                for (i = 0; i < 36; i++) {
                    if (!uuid[i]) {
                        r = 0 | Math.random() * 16
                        uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r]
                    }
                }
            }
            return uuid.join('');
        },
        //四舍五入取整数（保存几位）Math.round(price)
        //获取随机数（中英文都有的）
        /*getRnd  默认两个参数，第一个参数传数字，表示位数。
        *        第二个参数可不写，是布尔型，true和false都行。加上这个参数表示纯数字的随机数
        */
        getRnd: function (n, blean) {
            part1.randomNum = ''
            if (blean == '' || blean == true || blean == false) {
                for (var i = 0; i < n; i++) {
                    part1.randomNum += Math.floor(Math.random() * 10)
                }
            } else {
                for (var i = 0; i < n; i++) {
                    var j = parseInt(part1.ranStr.length * Math.random())
                    part1.randomNum += part1.ranStr.charAt(j)
                }
            }
            return part1.randomNum
        },
        //深拷贝 => 两个方法都无法拷贝函数，date，reg类型的对象;
        deepCopy: function (item,hash = new WeakMap()) {
            // var newarr = Array.isArray(item) ? [] : {}
            // for (var key in item) {
            //     if (item.hasOwnProperty(key)) {
            //         if (typeof item[key] === 'object' && item[key] !== null) {
            //             newarr[key] = this.deepCopy(item[key])
            //         } else {
            //             newarr[key] = item[key]
            //         }
            //     }
            // }
            // return newarr
            //只解决date，reg类型，其他的可以自己添加
            let cloneObj
            let Constructor = item.constructor
            switch(Constructor){
                case RegExp:
                    cloneObj = new Constructor(item)
                    break
                case Date:
                    cloneObj = new Constructor(item.getTime())
                    break
                default:
                    if(hash.has(item)) return hash.get(item)
                    cloneObj = new Constructor()
                    hash.set(item, cloneObj)
            }
            for (let key in item) {
                cloneObj[key] = (typeof item[key] === 'object' && item[key] !== null) ? this.deepCopy(item[key], hash) : item[key];
            }
            return cloneObj

        },
    }
    //获取链接中参数
    part1.getPara = function (name) {
        var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)')
        var r = (window.location.href.split('?')[1] || '').substr(0).match(reg)
        if (r != null) return decodeURIComponent(r[2])
        return null
    }
    part1.toStr = function (o) {
        return o ? o.toString() : ''
    }
    //对于电商项目的价格 设置保留n个小数<如果只传一个参数就默认的保留2位小数> toFixed 把数字转换为字符串
    part1.setTwoNum = function (price, n) {
        // if(price<0){ price = 0 };
        return isNaN(price) ? 0 : (part1.empty(n) ? new Number(price).toFixed(2) : new Number(price).toFixed(n))
    }
    //金额 转 千位符
    part1.toThousands = function (num) {
        num = num + ''
        var source = num.replace(/\,|\￥/g, '').split('.')
        source[0] = source[0].replace(new RegExp('(\\d)(?=(\\d{3})+$)', 'ig'), '$1,')
        return source.join('.')
    }

    part1.toNumber = function (inObj, p) {
        try {
            let d = parseFloat(inObj)
            return isNaN(d) ? 0 : (p ? d.toFixed(Math.abs(p)) : d)
        } catch (e) {
            // console.error('error: wfy.toNumber')
            // console.error(e)
            return 0
        }
    }
    // 返回字符串的实际长度, 一个汉字算2个长度
    part1.strlen = function (str) {
        var str = str || ''
        return str.replace(/[^\x00-\xff]/g, '**').length
    }
    //字符串超出省略   len 取双倍！比如要截取三个字 那么设置len参数为6  默认长度设置10吧
    part1.cutstr = function (str, len) {
        len = len || 10
        var restr = str
        var wlength = str.replace(/[^\x00-\xff]/g, '**').length
        if (wlength > len) {
            for (var k = len / 2; k < str.length; k++) {
                if (str.substr(0, k).replace(/[^\x00-\xff]/g, '**').length >= len) {
                    restr = str.substr(0, k) + '...'
                    break
                }
            }
        }
        return restr
    }

    /**
     * 数组根据数组对象中的某个属性值进行排序的方法
     * 使用例子：newArray.sort(wfy.sortBy('number',false)) //表示根据number属性降序排列;若第二个参数不传递，默认表示升序排序
     * var resarr = re.sort(wfy.sortBy('kcssje',false));//从大大小排列
     * @param attr 排序的属性 如number属性
     * @param rev true表示升序排列，false降序排序
     * */
    part1.sortBy = function (attr, rev) {
        //第二个参数没有传递 默认升序排列
        if (rev == undefined) {
            rev = 1
        } else {
            rev = (rev) ? 1 : -1
        }
        return function (a, b) {
            a = a[attr]
            b = b[attr]
            if (a < b) {
                return rev * -1
            }
            if (a > b) {
                return rev * 1
            }
            return 0
        }
    }
    /**
     * 对象数组根据时间排序
     * @param {*} obj  要排序的对象数组
     * @param {*} attr 时间的key值（那个属性）
     * @param {*} rev 默认或1 升序 -1降序
     * return 当前对象数组
     */
    part1.sortDate = function (obj, attr, rev) {
        return obj.sort(function (a, b) {
            return (new Date(a[attr]).getTime() - new Date(b[attr]).getTime()) * (rev ? rev : 1)
        })
    }

    /*
     * 汉子中文排序
     * 参数：arr 排序的数组; key 数组内的需要比较的元素属性
     * 使用例子：
     * 1. var arrs = ['南京', '北京', '上海', '杭州', '深圳']; 单纯的数组。key值不需要传
     * 2. [{name: '北京', code: '01', info: {province: '北京'}},
     * 比较的是name，传入的就是 'name'
     * 比较的是数组元素属性info内的province属性，传入的就是 'info.province'
     * eg wfy.sortChinese(shopinfo,'clientName');
     * console.log(shopinfo)--------直接修改原来的数据
     * */
    part1.sortChinese = function (arr, key) {
        /* 获取数组元素内需要比较的值 */
        var getValue = function (option) { // 参数： option 数组元素
            if (!key) return option
            var data = option
            key.split('.').filter(function (item) {
                data = data[item]
            })
            return data + ''
        }
        arr.sort(function (item1, item2) {
            return getValue(item1).localeCompare(getValue(item2), 'zh-CN')
        })
    }
    /**
     * 单据类详情 数据的删除和增加操作，已经存在的不添加（即 对象数组中 删除或增加对象）
     * @param {*} obj 被操作的单条数据 对象
     * @param {*} interData 被添加的数据  对象数组
     * @param {*} keys 对象中的key，一个key的时候可以使用字符串格式！，多个用数组
     * @param {*} oprType 操作类型 add 和 del
     * @param {*} isCover 布尔 true 为覆盖
     */
    part1.oprObjectArray = function (obj, interData, keys, oprType, isCover) {
        let keyList = this.isArray(keys) ? keys : [keys];
        if (oprType == "add") {
            let keyFlag = false;
            if (interData.length == 0) {
                keyFlag = true;
            } else {
                for (const index in interData) {
                    keyList.forEach(k => {
                        //只要任何一个不相同 就是true。表示 不同
                        if (interData[index][k] !== obj[k]) {
                            keyFlag = true;
                        }
                    })
                    if (keyFlag) {
                        if (isCover) interData[index] = obj;
                        break;
                    }
                }

            }
            keyFlag && interData.push(obj);
        }
        if (oprType == "del") {
            if (interData.length == 0) {
                return interData;
            } else {
                //一条一条的删
                let idx = -1;
                for (const i in interData) {
                    let arr1 = [];
                    let arr2 = [];
                    keyList.forEach(k => {
                        arr1.push(interData[i][k]);
                        arr2.push(obj[k]);
                    })
                    if (arr1.join(',') === arr2.join(',')) {
                        idx = i;
                        interData.splice(idx, 1);
                        break;
                    }

                }
            }
        }
        return interData;
    }
    //oprObjectArray 方法改成操作数组
    part1.oprObjectArrays = function (oprArr, interData, keys, oprType, isCover) {
        oprArr.forEach(obj => {
            this.oprObjectArray(obj, interData, keys, oprType, isCover)
        })
    }

    part1.getRandom = function (len) {
        //默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1
        var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
        var tempLen = chars.length,
            tempStr = ''
        for (var i = 0; i < len; ++i) {
            tempStr += chars.charAt(Math.floor(Math.random() * tempLen))
        }
        return tempStr
    }

    /**
     * Check if an element has a class
     * @param {HTMLElement} elm
     * @param {string} cls
     * @returns {boolean}
     */
    part1.hasClass = function (ele, cls) {
        return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'))
    }
    /**
     * Add class to element
     * @param {HTMLElement} elm
     * @param {string} cls
     */
    part1.addClass = function (ele, cls) {
        if (!this.hasClass(ele, cls)) ele.className += ' ' + cls
    }

    /**
     * Remove class from element
     * @param {HTMLElement} elm
     * @param {string} cls
     */
    part1.removeClass = function (ele, cls) {
        if (this.hasClass(ele, cls)) {
            const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)')
            ele.className = ele.className.replace(reg, ' ')
        }
    }
    /**
     * 简单防抖
     * @param {*} fn 要防抖的函数
     * @param {*} delay 防抖的毫秒数
     * @returns
     */
    part1.debounce = function (fn, delay = 100) {
        let timer = null
        return function () {
            let args = arguments
            if (timer) {
                clearTimeout(timer)
            }
            timer = setTimeout(() => {
                fn.apply(this, args)
            }, delay)
        }
    }
    /**
     * 选择图片后 转base64格式
     * @param {*} file
     * @returns
     */
    part1.uploadImgToBase64 = function (file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader()
            reader.readAsDataURL(file)
            reader.onload = function () {
                resolve(reader)
            }
            reader.onerror = reject
        })
    }
    //判断两个对象是否相等
    part1.isObjectValueEqual = function (a, b) {
        let aProps = Object.getOwnPropertyNames(a)
        let bProps = Object.getOwnPropertyNames(b)
        if (aProps.length != bProps.length) {
            return false
        }
        for (let i = 0; i < aProps.length; i++) {
            let propName = aProps[i]

            let propA = a[propName]
            let propB = b[propName]
            if ((typeof (propA) === 'object')) {
                if (this.isObjectValueEqual(propA, propB)) {
                    return true
                } else {
                    return false
                }
            } else if (propA !== propB) {
                return false
            } else { }
        }
        return true
    }
    /**
     * 四舍五入
     * @param num 待四舍五入的数字
     * @param p   保留小数位数
     * @return {number}
     */
    part1.round = function (num, p) {
        if (isNaN(p) || parseInt(p) < 0) {
            p = 0
        }
        if (isNaN(num)) {
            return 0
        }
        const cm = Math.pow(10, p)
        return Math.round(num * cm) / cm
    }
    // 复制到粘贴板
    part1.copyToClipboard = (text) => {
        // navigator.clipboard.writeText(text)
        // 	.then(function () {
        // 		console.log('Text copied to clipboard')
        // 		this.$message.success('已复制内容到剪贴板')
        // 	})
        // 	.catch(function (err) {
        // 		console.error('Failed to copy text: ', err)
        // 	})

        //浏览器禁用了非安全域的 navigator.clipboard 对象
        //在线上环境会报错 TypeError: Cannot read properties of undefined (reading 'writeText')
        if (!navigator.clipboard && window.isSecureContext) {
            return navigator.clipboard.writeText(text)
        } else {
            // 判断是否支持拷贝
            if (!document.execCommand('copy')) return Promise.reject()
            // 创建标签，并隐藏
            const textArea = document.createElement('textarea')
            textArea.style.position = 'fixed'
            textArea.style.top = textArea.style.left = '-100vh'
            textArea.style.opacity = '0'
            textArea.value = text
            document.body.appendChild(textArea)
            // 聚焦、复制
            textArea.focus()
            textArea.select()
            return new Promise((resolve, reject) => {
                // 不知为何，必须写这个三目，不然copy不上
                document.execCommand('copy') ? resolve() : reject()
                textArea.remove()
            })
        }
    }

    /**
     * operObjectInArr 升级版
     * 区别：已经存在的 可以根据参数 设置 不添加 还是 覆盖
     * @param {*} fromArr 要操作的数据 对象数组
     * @param {*} toArr 被添加的数据  对象数组
     * @param {*} key fromArr的list中唯一值的 key
     * @param {*} operType 操作类型 add 和 del
     * @param {*} listType 布尔 true 为覆盖
     */
     part1.operObjectInArrs = function(fromArr, toArr, key, operType, listType = false) {
        if (operType == 'add') {
            if (!fromArr) {
                return false
            } else {
                fromArr.forEach((item, index) => {
                    var flag = false
                    toArr.forEach((list, sum) => {
                        if (list[key] == item[key]) {
                            flag = true //存在  就是true
                            if (listType) {
                                toArr[sum] = item
                            }
                        }
                    })
                    if (!flag) {
                        toArr.push(item)
                    }
                })
            }
        }
        if (operType == 'del') {
            //循环一条一条的删
            var index = -1
            if (!fromArr) {
                return false
            } else {
                fromArr.map((item) => {
                    var values = item[key] //要删除对象的 某个唯一值
                    for (const i in toArr) {
                        if (toArr[i][key] == values) {
                            index = i
                            break
                        }
                    }
                    if (index != -1) {
                        toArr.splice(index, 1)
                    }
                })
            }
        }
        return toArr
    }
    /**
     * 2021/5/24 operObjectInArrs 再升级 --- key值存在多个的情况
     * @param {*} operArr 要操作的数据 对象数组
     * @param {*} updateArr 被添加的数据  对象数组
     * @param {*} key 对象中的key，一个key的时候可以使用字符串格式！，多个用数组
     * @param {*} operType 操作类型 add 和 del
     * @param {*} listType 布尔 true 为覆盖
     */
    part1.operObjectArray = function(operArr, updateArr, key, operType, listType = false) {
        //operArr updateArr 数据准确性不做判断
        let keys = this.isArray(key) ? key : [key]
            //添加
        if (operType == 'add') {
            operArr.some((item) => {
                let keyFlag = false
                if (updateArr.length == 0) {
                    updateArr.push(item)
                } else {
                    updateArr.forEach((element, index) => {
                        //没想出来 如何动态的实现不定key个数的 并且判断，先暂时挨个情况判断
                        if (keys.length == 1) {
                            if (element[keys[0]] != item[keys[0]]) {
                                keyFlag = true
                            }
                        }
                        if (keys.length == 2) {
                            if ((element[keys[0]] == item[keys[0]]) && (element[keys[1]] == item[keys[1]])) {
                                keyFlag = true
                            }
                        }
                        if (keyFlag && listType) {
                            updateArr[index] = item
                        }
                    });
                    !keyFlag && updateArr.push(item)
                }
            })
        }
        if (operType == 'del') {
            //循环一条一条的删
            let idx = -1
            operArr.some((item) => {
                if (updateArr.length == 0) {
                    return updateArr
                } else {
                    updateArr.forEach((element, index) => {
                        if (keys.length == 1) {
                            if (element[keys[0]] == item[keys[0]]) {
                                idx = index
                            }
                        }
                        if (keys.length == 2) {
                            if ((element[keys[0]] == item[keys[0]]) && (element[keys[1]] == item[keys[1]])) {
                                idx = index
                            }
                        }
                    })
                    if (idx != -1) {
                        updateArr.splice(idx, 1)
                    }
                }
            })
        }
        return updateArr
    }

    /**
     * 第二部分 gotoPart2 时间函数   moment.js有个专门的时间函数库
     *
     */
    var now = new Date() //当前日期
    var pre = new Date() //上月日期
    pre.setDate(1) //设置为1号
    pre.setMonth(pre.getMonth() - 1)
    var time = {
        now: now, //当前日期
        nowDay: now.getDate(), //当前日
        nowDayOfWeek: now.getDay(), //
        nowMonth: now.getMonth(), //
        nowYear: now.getFullYear(), //
        preYear: pre.getFullYear(), //上个月的年份
        preMonth: pre.getMonth() //上个月的月份
    }
    var part2 = {
        /**
         * 将数据的长度补齐 eg得到的毫秒数 秒数 月份等数据 都统一一定的长度
         * @param {*} num
         * @param {*} len
         * wfy.formatDateNum(58,6) ->000058
         */
        formatDateNum: function (num, len = 2) {
            var addlen = num.toString().length
            while (addlen < len) {
                num = '0' + num
                addlen++
            }
            return num
        },
        /**
         * 当你看到这个代码 你估计不会知道他的使用场景！我不写明它是干嘛的，有兴趣你自己去探索吧~
         * 但是 它是打败度娘介绍中千篇一律的方法，经过实际检验有效的！！，
         * @param {*} numb
         * @returns
         */
        formatExcelDate: function (numb) {
            const d = numb - 1
            const t = Math.round((d - Math.floor(d)) * 24 * 60 * 60)
            return this.format('yyyy-MM-dd HH:mm:ss', new Date(1900, 0, d, 0, 0, t))
        },
        // 将时间戳格式化
        getLocalTime: function (time) {
            if (!time || time == '') {
                return ''
            } else {
                return wfy.format('yyyy-MM-dd HH:mm:ss', new Date(parseInt(time)))
            }
        },
        //获取当前时间。并自定义时间 连接格式 / - . 默认 用-
        format: function (fmt, date) {
            fmt = (fmt || '') + ''
            date = new Date(date || new Date())
            var map = {}
            map['M+'] = date.getMonth() + 1
            map['d+'] = date.getDate()
            map['H+'] = date.getHours()
            map['m+'] = date.getMinutes()
            map['s+'] = date.getSeconds()
            map['q+'] = Math.floor((date.getMonth() + 3) / 3)
            if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
            if (/(W+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, ['日', '一', '二', '三', '四', '五', '六'][date.getDay()])
            if (/(S+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, date.getMilliseconds() + '')
            for (var key in map) {
                if (new RegExp('(' + key + ')').test(fmt)) {
                    fmt = fmt.replace(RegExp.$1, RegExp.$1.length === 1 ? map[key] : ('00' + map[key]).substr(('' + map[key]).length))
                }
            }
            return fmt
        },
        getDateDiff: function(date) {
            //将xxxx-xx-xx的时间格式，转换为 xxxx/xx/xx的格式
            let startTime = date.replace(/\-/g, "/");
            return startTime;
        },
        /**
         * 日期 默认拼接 时分秒 开始是00:00:00,截止是23:59:59 默认是开始
         * @param {*} date
         * @param {*} symbol
         */
        dataPicker(date, symbol = true) {
            //值考虑空和 日期
            if (!this.empty(date)) {
                var d = new Date(date).getTime()
                d = new Date(d)
                d.setHours(symbol ? 0 : 23)
                d.setMinutes(symbol ? 0 : 59)
                d.setSeconds(symbol ? 0 : 59)
                return part2.format('yyyy-MM-dd HH:mm:ss', d)
            } else {
                return date
            }

        },
        formatDate: function (date, symbol) {
            //symbol 链接符号 默认 不写为空 20180831格式~~~
            var myyear = date.getFullYear()
            var mymonth = date.getMonth() + 1
            var myweekday = date.getDate()
            if (mymonth < 10) {
                mymonth = '0' + mymonth
            }
            if (myweekday < 10) {
                myweekday = '0' + myweekday
            }
            if (!symbol) symbol = ''
            return (myyear + symbol + mymonth + symbol + myweekday) //----------
        },
        /**
         * //获取两个日期之间所有日期  getAll('2017-02-27', '2017-03-02'); //2017-02-27  2017-02-28 2017-03-01 2017-03-02
         * @param {*} begin
         * @param {*} end
         * @returns
         */
        getAllDay: function (begin, end) {

            var ab = begin.split('-')
            var ae = end.split('-')
            var db = new Date()
            var arr = []
            db.setUTCFullYear(ab[0], ab[1] - 1, ab[2])
            var de = new Date()
            de.setUTCFullYear(ae[0], ae[1] - 1, ae[2])
            var unixDb = db.getTime()
            var unixDe = de.getTime()
            for (var k = unixDb; k <= unixDe;) {
                k = k + 24 * 60 * 60 * 1000
                arr.push(wfy.formatDate(new Date(parseInt(k))))
            }
            return arr
        },
        ////获得今年 某月的天数   nowYear用的是now当前的
        getMonthDays: function (myMonth) {
            var monthStartDate = new Date(time.nowYear, myMonth, 1) // 本月的第一天  格式 ：2016 01 01
            var monthEndDate = new Date(time.nowYear, myMonth + 1, 1) //下个月的第一天  相减得到天数的毫秒
            var days = (monthEndDate - monthStartDate) / (1000 * 60 * 60 * 24) //
            return days
            //console.log(time.getMonthDays(8)) 注意 参数是从0开始的  8标识 第9个月
        },
        //计算 某年某月天数(用来优化上面的方法)
        getSomeMonthDays: function (year, month) {
            return new Date(year, month, 0).getDate() //0表示下月的第0天，上月的最后一天,月份从0开始记数
        },
        //获取当前 季度的 开始 月份
        getQuarterStartMonth: function () {
            var quarterStartMonth = 0
            if (time.nowMonth < 3) {
                quarterStartMonth = 0
            }
            if (2 < time.nowMonth && time.nowMonth < 6) {
                quarterStartMonth = 3
            }
            if (5 < time.nowMonth && time.nowMonth < 9) {
                quarterStartMonth = 6
            }
            if (time.nowMonth > 8) {
                quarterStartMonth = 9
            }
            return quarterStartMonth
        },
        //获取 本周 开始 日期
        getWeekStartDate: function () {
            //nowDayOfWeek本周第几天
            //nowDay 本月的日期。减去 本周已经过了的天数。得到 本周开始的日期格式。
            //然后 new Date
            var weekStartDate = new Date(time.nowYear, time.nowMonth, time.nowDay - time.nowDayOfWeek)
            //console.error(weekStartDate)  得到：time.js:41 Sun Jan 08 2017 00:00:00 GMT+0800 (中国标准时间)
            return part2.formatDate(weekStartDate, '-')
        },
        //获取本周 结束 的日期
        getWeekEndDate: function () {
            var weekEndDate = new Date(time.nowYear, time.nowMonth, time.nowDay + (6 - time.nowDayOfWeek))
            return part2.formatDate(weekEndDate, '-')
        },
        //获取本月的 开始 日期
        getMonthStartDate: function () {
            var monthStartDate = new Date(time.nowYear, time.nowMonth, 1)
            return part2.formatDate(monthStartDate, '-')
        },
        //本月 结束  时间
        getMonthEndDate: function () {
            var monthEndDate = new Date(time.nowYear, time.nowMonth, part2.getMonthDays(time.nowMonth))
            return part2.formatDate(monthEndDate, '-')
        },

        getMonthBegin: function(d) {
            if (!d) { d = new Date() }
            return new Date(d.getFullYear(), d.getMonth(), 1)
        },
        getMonthEnd: function(d) {
            if (!d) { d = new Date() }
            return new Date(d.getFullYear(), d.getMonth() + 1, 0)
        },


        //上个月的 开始 日期
        getPreMonthStartDate: function () {
            var preMonthStartDate = new Date(time.preYear, time.preMonth, 1)
            return part2.formatDate(preMonthStartDate, '-')
        },
        //上个月的 结束 日期
        getPreMonthEndDate: function () {
            var preMonthEndDate = new Date(time.preYear, time.preMonth, part2.getMonthDays(time.preMonth))
            return part2.formatDate(preMonthEndDate, '-')
        },

        //本季度的 开始日期
        getQuarterStartDate: function () {
            var quarterStartDate = new Date(time.nowYear, part2.getQuarterStartMonth(), 1)
            return part2.formatDate(quarterStartDate, '-')
        },
        //本季度的 结束 日期
        getQuarterEndDate: function () {
            var quarterEndMonth = part2.getQuarterStartMonth() + 2
            var quarterStartDate = new Date(time.nowYear, quarterEndMonth, part2.getMonthDays(quarterEndMonth))
            return part2.formatDate(quarterStartDate, '-')
        },
        //年的开始 就简单了 由年份 直接拼写吧
        getYearStartDate: function () {
            return time.nowYear + '-01' + '-01'
        },
        getYearEndDate: function () {
            return time.nowYear + '-12' + '-31'
        },
        //获取某个日期num天后的 日期 没加time的为空判断 使用的时候加以验证
        getNextDay: function (time, num) {
            var d = new Date(time).getTime()
            d = d + 1000 * 60 * 60 * 24 * num
            d = new Date(d)
            return part2.formatDate(d, '-')
        },
        //获取某个日期num前后的 日期
        getPreDay: function (time, num) {
            var d = new Date(time).getTime()
            d = d - 1000 * 60 * 60 * 24 * num
            d = new Date(d)
            return part2.formatDate(d, '-')
        },
        // 托管12个月 获取某个日期以后 几个月的日期
        getNumMonday: function (time, month) {
            var time = new Date(time)
            var y = time.getFullYear()
            var m
            if (time.getMonth() + month + 1 > 12) {
                y = y + 1
                m = time.getMonth() + month - 11
            } else {
                m = time.getMonth() + month + 1
            }
            var d = time.getDate()
            return y + '-' + m + '-' + d
        }
    }
    window.wfy = Object.assign({}, part1, part2,);

    /**
     * 临时定义了一个win对象
     * 这个win对象没有实际意义
     * 只是为了少更新一部分代码，以尽快打到测试的目的
     * win对象仅有一个init方法，且init仅返回一个空的Promise
     * @type {{init(): Promise<unknown>}}
     */
    window.win = {
        init() {
            return new Promise((resolve) => {
                resolve(true)
            })
        }
    }
})(window)
